﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Reflection;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Microsoft.Win32;

using Elegant.Ui;

namespace iPdf
{
    class FontFamilyComboBox : TataComboBox
    {
        #region Properties

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new System.Windows.Forms.ComboBox.ObjectCollection Items
        {
            get { return base.Items; }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new int ItemHeight
        {
            get
            {
                return base.ItemHeight;
            }
            set { base.ItemHeight = value; }
        }
        
        #endregion

        #region Ctor
        public FontFamilyComboBox()
        {
            DrawMode = DrawMode.OwnerDrawFixed;
            ItemHeight = ScaleSize(new Size(0, 30)).Height;
            DisplayMember = "Name";
            DropDownHeight = 200;
            DropDownWidth = 300;
            
            this.TextEditor.TextChanged += new EventHandler(TextEditor_TextChanged);
            //use the name property of FontFamily class as the screen tip
            ItemScreentipTextPropertyName = "Name";
        }
        #endregion

        #region Methods
        private void CacheVisibleFonts()
        {
            int visibleItemCount = DropDownHeight / ItemHeight;
            using (Bitmap bmp = new Bitmap(100, 100))
            {
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    for (int i = 0; i < visibleItemCount; i++)
                    {
                        using (System.Drawing.Font font = CreateSampleFont((FontFamily)Items[i], 12))
                            g.DrawString(font.FontFamily.Name, font, SystemBrushes.Control, 0, 0);
                    }
                }
            }
            
        }

        protected override void OnDropDown()
        {
            base.OnDropDown();

            CacheVisibleFonts();
            Elegant.Ui.WinApi.SetFocus(this.TextEditor.Handle);
        }

        public void Load()
        {
            AutoCompleteMode = AutoCompleteMode.Append;
            AutoCompleteSource = AutoCompleteSource.CustomSource;

            AutoCompleteStringCollection autoCompleteStringCollection = new AutoCompleteStringCollection();
            foreach (FontFamily f in FontFamily.Families)
                autoCompleteStringCollection.Add(f.Name);
            AutoCompleteCustomSource = autoCompleteStringCollection;

            DataSource = FontFamily.Families;
        }

        protected override void OnDrawItem(DrawComboBoxItemEventArgs e)
        {
            const string badFontFamily = "Cambria Math";
            if (e.IsSelected)
                e.PaintSelectedBackground();
            else
                e.PaintNormalBackground();

            FontFamily fontFamily = (FontFamily)Items[e.ItemIndex];
            string fontName = fontFamily.Name;
            //this is a workaround for .net framework's bug of font creating font for "Cambria Math" font family -
            //the font height is too large
            if (fontName == badFontFamily)
            {
                fontFamily = (FontFamily)Items[e.ItemIndex - 1];
            }
            using (System.Drawing.Font font = CreateSampleFont(fontFamily, 12))
            {
                
                TextRenderer.DrawText(
                    e.Graphics,
                    fontName,
                    font,
                    e.BoundsRelativeToPopup,
                    e.TextColor,
                    TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
            }
        }

        private System.Drawing.Font CreateSampleFont(FontFamily fontFamily, float size)
        {
            FontStyle[] availableStyles = (FontStyle[])Enum.GetValues(typeof(FontStyle));

            FontStyle? supportedStyle = null;
            foreach (FontStyle fontStyle in availableStyles)
            {
                if (fontFamily.IsStyleAvailable(fontStyle))
                {
                    supportedStyle = fontStyle;
                    break;
                }
            }

            if (supportedStyle == null)
                return new System.Drawing.Font(Font.FontFamily, size);

            System.Drawing.Font font = new System.Drawing.Font(fontFamily, size, supportedStyle.Value);

            return font;
        }

        private void TextEditor_TextChanged(object sender, EventArgs e)
        {
            string text = this.TextEditor.Text;
            if (string.IsNullOrEmpty(text)) 
            {
                return;
            }

            int index = this.FindString(text);
            if (index == -1) 
            {
                return;
            }
            
            if (this.DroppedDown) 
            {
                this.EnsureItemIsVisibleInDropDown(index);
                this.PopupItems[index].Select();
            }
        }

        #endregion
    }
}
